import { describe, it, expect, vi } from 'vitest'
import { render, screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import * as clipboard from '../lib/clipboard'
import { DecisionCard } from './DecisionCard'
import type { DecisionRecord } from '../types'

/**
 * DecisionCard 组件测试 - 验证新增字段的显示
 *
 * 测试场景：
 * - update_stop_loss 显示 new_stop_loss 字段
 * - update_take_profit 显示 new_take_profit 字段
 * - partial_close 显示 close_percentage 字段
 */

describe('DecisionCard - New Fields Display', () => {
  const baseDecision: DecisionRecord = {
    cycle_number: 1,
    timestamp: '2025-01-16T10:00:00Z',
    success: true,
    decisions: [],
    execution_log: [],
    account_state: {
      total_balance: 10000,
      available_balance: 5000,
      total_unrealized_profit: 0,
      position_count: 0,
      margin_used_pct: 0,
    },
    input_prompt: '',
    cot_trace: '',
    error_message: '',
    decision_json: '{}',
    positions: [],
    candidate_coins: [],
  }

  it('should display new_stop_loss field for update_stop_loss action', () => {
    const decision: DecisionRecord = {
      ...baseDecision,
      decisions: [
        {
          action: 'update_stop_loss',
          symbol: 'BTCUSDT',
          price: 50000.0,
          new_stop_loss: 48000.0,
          quantity: 0,
          leverage: 0,
          order_id: 0,
          timestamp: '2025-01-16T10:00:00Z',
          success: true,
          error: '',
        },
      ],
    }

    render(<DecisionCard decision={decision} language="en" />)

    // 验证 symbol 显示
    expect(screen.getByText('BTCUSDT')).toBeInTheDocument()

    // 验证 action 显示
    expect(screen.getByText('update_stop_loss')).toBeInTheDocument()

    // 验证 new_stop_loss 显示（现在在同一行，用emoji表示）
    expect(screen.getByText(/🛑.*48000\.00/)).toBeInTheDocument()

    // 验证价格显示
    expect(screen.getByText(/@ \$50000\.00/)).toBeInTheDocument()
  })

  it('should display new_take_profit field for update_take_profit action', () => {
    const decision: DecisionRecord = {
      ...baseDecision,
      decisions: [
        {
          action: 'update_take_profit',
          symbol: 'ETHUSDT',
          price: 3000.0,
          new_take_profit: 3200.0,
          quantity: 0,
          leverage: 0,
          order_id: 0,
          timestamp: '2025-01-16T10:00:00Z',
          success: true,
          error: '',
        },
      ],
    }

    render(<DecisionCard decision={decision} language="en" />)

    expect(screen.getByText('ETHUSDT')).toBeInTheDocument()
    expect(screen.getByText('update_take_profit')).toBeInTheDocument()

    // 验证 new_take_profit 显示（现在在同一行，用emoji表示）
    expect(screen.getByText(/🎯.*3200\.00/)).toBeInTheDocument()

    // 验证价格显示
    expect(screen.getByText(/@ \$3000\.00/)).toBeInTheDocument()
  })

  it('should display close_percentage field for partial_close action', () => {
    const decision: DecisionRecord = {
      ...baseDecision,
      decisions: [
        {
          action: 'partial_close',
          symbol: 'SOLUSDT',
          price: 100.0,
          quantity: 5.0,
          close_percentage: 50.0,
          leverage: 0,
          order_id: 0,
          timestamp: '2025-01-16T10:00:00Z',
          success: true,
          error: '',
        },
      ],
    }

    render(<DecisionCard decision={decision} language="en" />)

    expect(screen.getByText('SOLUSDT')).toBeInTheDocument()
    expect(screen.getByText('partial_close')).toBeInTheDocument()

    // 验证 close_percentage 显示（现在在同一行，用emoji表示）
    expect(screen.getByText(/📊.*50\.0%/)).toBeInTheDocument()

    // 验证 quantity 显示（现在在同一行，直接显示数字）
    expect(screen.getByText(/5\.0000/)).toBeInTheDocument()

    // 验证价格显示
    expect(screen.getByText(/@ \$100\.00/)).toBeInTheDocument()
  })

  it('should display multiple actions with different new fields', () => {
    const decision: DecisionRecord = {
      ...baseDecision,
      decisions: [
        {
          action: 'update_stop_loss',
          symbol: 'BTCUSDT',
          price: 50000.0,
          new_stop_loss: 48000.0,
          quantity: 0,
          leverage: 0,
          order_id: 0,
          timestamp: '2025-01-16T10:00:00Z',
          success: true,
          error: '',
        },
        {
          action: 'update_take_profit',
          symbol: 'ETHUSDT',
          price: 3000.0,
          new_take_profit: 3200.0,
          quantity: 0,
          leverage: 0,
          order_id: 0,
          timestamp: '2025-01-16T10:00:00Z',
          success: true,
          error: '',
        },
        {
          action: 'partial_close',
          symbol: 'SOLUSDT',
          price: 100.0,
          quantity: 5.0,
          close_percentage: 50.0,
          leverage: 0,
          order_id: 0,
          timestamp: '2025-01-16T10:00:00Z',
          success: true,
          error: '',
        },
      ],
    }

    render(<DecisionCard decision={decision} language="en" />)

    // 验证所有 symbols 都显示
    expect(screen.getByText('BTCUSDT')).toBeInTheDocument()
    expect(screen.getByText('ETHUSDT')).toBeInTheDocument()
    expect(screen.getByText('SOLUSDT')).toBeInTheDocument()

    // 验证所有 actions 都显示
    expect(screen.getByText('update_stop_loss')).toBeInTheDocument()
    expect(screen.getByText('update_take_profit')).toBeInTheDocument()
    expect(screen.getByText('partial_close')).toBeInTheDocument()
  })

  it('should handle missing optional fields gracefully', () => {
    const decision: DecisionRecord = {
      ...baseDecision,
      decisions: [
        {
          action: 'update_stop_loss',
          symbol: 'BTCUSDT',
          price: 50000.0,
          // new_stop_loss 字段缺失
          quantity: 0,
          leverage: 0,
          order_id: 0,
          timestamp: '2025-01-16T10:00:00Z',
          success: true,
          error: '',
        },
      ],
    }

    // 应该不会崩溃，正常渲染
    render(<DecisionCard decision={decision} language="en" />)

    expect(screen.getByText('BTCUSDT')).toBeInTheDocument()
    expect(screen.getByText('update_stop_loss')).toBeInTheDocument()
  })

  it('should display action source and plan_id when present', () => {
    const decision: DecisionRecord = {
      ...baseDecision,
      decisions: [
        {
          action: 'place_limit',
          symbol: 'SOLUSDT',
          price: 100.0,
          quantity: 1.0,
          leverage: 1,
          order_id: 123,
          timestamp: '2025-01-16T10:00:00Z',
          success: true,
          error: '',
          source: 'martingale',
          plan_id: 'eb9917a0-1234-5678-90ab-cdef12345678',
        },
      ],
    }

    render(<DecisionCard decision={decision} language="en" />)

    expect(screen.getByText('SOLUSDT')).toBeInTheDocument()
    expect(screen.getByText('place_limit')).toBeInTheDocument()
    // Source badge
    expect(screen.getByText('martingale')).toBeInTheDocument()
    // Plan ID (truncated shown in UI)
    expect(screen.getByText(/Plan: eb9917a0/)).toBeInTheDocument()
  })

  it('should copy plan id when clicking the plan copy button', async () => {
    const decision: DecisionRecord = {
      ...baseDecision,
      decisions: [
        {
          action: 'place_limit',
          symbol: 'SOLUSDT',
          price: 100.0,
          quantity: 1.0,
          leverage: 1,
          order_id: 123,
          timestamp: '2025-01-16T10:00:00Z',
          success: true,
          error: '',
          source: 'martingale',
          plan_id: 'eb9917a0-1234-5678-90ab-cdef12345678',
        },
      ],
    }

    const spy = vi
      .spyOn(clipboard, 'copyWithToast')
      .mockResolvedValue(true as any)
    render(<DecisionCard decision={decision} language="en" />)

    // aria-label includes full plan id
    const btn = screen.getByLabelText(
      'Copy Plan eb9917a0-1234-5678-90ab-cdef12345678'
    )
    expect(btn).toBeInTheDocument()
    await userEvent.click(btn)
    expect(spy).toHaveBeenCalledWith('eb9917a0-1234-5678-90ab-cdef12345678')
  })
})

/**
 * 数据类型验证测试
 * 确保新字段的类型定义正确
 */
describe('DecisionCard - Data Type Validation', () => {
  it('should accept valid new_stop_loss number', () => {
    const validAction = {
      action: 'update_stop_loss',
      symbol: 'BTCUSDT',
      price: 50000.0,
      new_stop_loss: 48000.0,
      quantity: 0,
      leverage: 0,
      order_id: 0,
      timestamp: '2025-01-16T10:00:00Z',
      success: true,
      error: '',
    }

    expect(typeof validAction.new_stop_loss).toBe('number')
    expect(validAction.new_stop_loss).toBeGreaterThan(0)
  })

  it('should accept valid new_take_profit number', () => {
    const validAction = {
      action: 'update_take_profit',
      symbol: 'ETHUSDT',
      price: 3000.0,
      new_take_profit: 3200.0,
      quantity: 0,
      leverage: 0,
      order_id: 0,
      timestamp: '2025-01-16T10:00:00Z',
      success: true,
      error: '',
    }

    expect(typeof validAction.new_take_profit).toBe('number')
    expect(validAction.new_take_profit).toBeGreaterThan(0)
  })

  it('should accept valid close_percentage number in range 0-100', () => {
    const validAction = {
      action: 'partial_close',
      symbol: 'SOLUSDT',
      price: 100.0,
      quantity: 5.0,
      close_percentage: 50.0,
      leverage: 0,
      order_id: 0,
      timestamp: '2025-01-16T10:00:00Z',
      success: true,
      error: '',
    }

    expect(typeof validAction.close_percentage).toBe('number')
    expect(validAction.close_percentage).toBeGreaterThan(0)
    expect(validAction.close_percentage).toBeLessThanOrEqual(100)
  })
})
